<template>
	<view class="bar-charts-com">
		<view class="chart-title">
			<text>图表分析</text>
		</view>
		<view class="chart" :id="'chart-'+uid">

		</view>
	</view>
</template>
<script>
	import {
		v4
	} from 'uuid'
	import * as echarts from 'echarts'
	import {
		getRandomColor,
		hexToHexWithAlpha
	} from "@/util/constant";

	/**
	 * @description 柱状图组件
	 * source 数据源 {xData:[],yData:{aaa:[],bbb:[]},yLabel:''} yData 若需要多条柱子则在对象中传入多组Data，对象的Key为系列名 yLabel为Y轴上的名称
	 * stack 是否堆叠值
	 * legend 是否显示图例
	 * grid 布局
	 * barRadius 柱子圆角 分别为 左上 右上 右下 左下
	 * barAlpha 柱子透明度 0-100
	 * barGradient 柱子是否渐变 为true时barAlpha失效
	 * barWidth 柱子宽度 不传值为auto
	 * barGap 柱子间隔 百分比 不传值为auto
	 * alignWithLabel x坐标轴刻度线和标签是否对齐
	 */
	export default {
		name: 'BarCharts',
		props: {
			source: {
				type: Object,
				required: true,
			},
			loading: {
				type: Boolean,
				default: true
			},
			legend: {
				type: Boolean,
				default: false
			},
			grid: {
				type: Object,
				default: () => {
					return {
						top: 40,
						bottom: 30,
						left: 20,
						right: 10
					}
				}
			},
			barRadius: {
				type: Array,
				default: () => {
					return [30, 30, 0, 0]
				}
			},
			barAlpha: {
				type: Number,
				default: 100
			},
			barGradient: {
				type: Boolean,
				default: false
			},
			barWidth: {
				type: Number,
				default: 0
			},
			barGap: {
				type: Number,
				default: null
			},
			stack: {
				type: Boolean,
				default: false
			}
		},
		watch: {
			source: {
				deep: true,
				immediate: true,
				handler(val) {
					this.$nextTick(() => {
						if (val) {
							if ((Array.isArray(val) && val.length) || Object.keys(val).length) {
								const option = this.getOption();
								this.getChart()
								this.chart.setOption(option)
							}
						}
					})
				}
			},
			loading: {
				immediate: true,
				handler(val) {
					this.$nextTick(() => {
						this.getChart()
						if (val) {
							this.chart.showLoading({
								text: '加载中',
								textColor: '#fff',
								maskColor: 'rgba(0,0,0,0)'
							})
						} else {
							this.chart.hideLoading()
						}
					})
				}
			}
		},
		data() {
			return {
				chart: null,
				uid: v4()
			}
		},
		methods: {
			getChart() {
				this.chart = this.chart || echarts.init(document.getElementById('chart-' + this.uid))
			},
			getOption() {
				const keys = Object.keys(this.source.yData)
				const color = getRandomColor(keys.length)
				const series = keys.map((item, index) => {
					const value = this.source.yData[item]
					let result = {
						name: item,
						type: 'bar',
						data: value
					}
					const currentColor = color[index]
					const colorOption = this.barGradient ? new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
							offset: 0,
							color: currentColor
						},
						{
							offset: 1,
							color: hexToHexWithAlpha(currentColor, 30)
						},
					]) : hexToHexWithAlpha(currentColor, this.barAlpha)
					result.itemStyle = {
						color: colorOption,
						borderRadius: this.barRadius
					}
					result.stack = this.stack;
					if (this.barWidth) {
						result.barWidth = this.barWidth
					}
					if (this.barGap !== null) {
						result.barGap = this.barGap + '%';
					}
					return result
				})
				
				// 修正grid配置，确保不出现负值
				const gridConfig = { ...this.grid };
				if (gridConfig.bottom < 0) gridConfig.bottom = 10;
				if (gridConfig.top < 0) gridConfig.top = 10;
				if (gridConfig.left < 0) gridConfig.left = 10;
				if (gridConfig.right < 0) gridConfig.right = 10;
				
				let option = {
					color,
					grid: {
						...gridConfig,
						containLabel: true
					},
					xAxis: {
						type: 'category',
						data: this.source.xData,
						axisLabel: {
							color: '#A3A3C9',
							rotate: 30,
							fontSize: 10,
							formatter: (value) => {
								let ret = '';
								let maxLength = 4;
								let valLength = value.length;
								let rowN = Math.ceil(valLength / maxLength);
								if (rowN > 1) {
									for (let i = 0; i < rowN; i++) {
										let temp = '';
										const start = i * maxLength;
										const end = start + maxLength;
										temp = value.substring(start, end) + '\n';
										ret += temp;
									}
									return ret;
								} else {
									return value;
								}
							}
						},
						axisLine: {
							lineStyle: {
								color: '#0B3771'
							}
						},
						axisTick: {
							show: false
						},
					},
					yAxis: {
						type: 'value',
						name: this.source.yLabel || '',
						nameTextStyle: {
							color: '#A3A3C9'
						},
						axisLabel: {
							color: '#A3A3C9'
						},
						splitLine: {
							lineStyle: {
								color: 'rgba(199,199,200,0.1)',
								width: 1,
								type: 'solid'
							}
						}
					},
					series: series,
					tooltip: {
						trigger: 'axis'

					}
				}
				if (this.legend) {
					option.legend = {
						data: Object.keys(this.source.yData),
						textStyle: {
							color: '#fff'
						}
					}
				}
				return option
			}
		},
		beforeDestroy() {
			this.chart && this.chart.dispose();
			this.chart = null
		}
	}
</script>
<style lang="scss" scoped>
	.bar-charts-com {
		width: 100%;
		height: 500rpx;
		margin-bottom: 20rpx;
		overflow: visible;

		.chart-title {
			padding: 20rpx 0;
			font-size: 32rpx;
			font-weight: bold;
			text-align: center;
			color: #333;
			background: linear-gradient(90deg, rgba(0,103,255,0.1) 0%, rgba(0,103,255,0.3) 50%, rgba(0,103,255,0.1) 100%);
			border-radius: 8rpx;
			margin-bottom: 10rpx;
		}

		.chart {
			width: 100%;
			height: 100%;
			min-height: 400rpx;
		}
	}
</style>